﻿#region summary

// Copyright (c)  MOKEYISH. All rights reserved.
// Licensed under the MIT License, See License.txt in the project root for license information.

#endregion

using System;
using System.Diagnostics;
using NSQL.Generator;

namespace NSQL.Expressions
{
    [DebuggerDisplay("Column:{Name}")]
    public class ColumnExpression : IColumnExpression
    {
        public string Name { get; }
        public int Id { get; }
        public bool Delimited { get; }
        public byte Sign { get; }

        public ColumnExpression(string columnName, bool delimited = false)
        {
            if (columnName is null) throw new ArgumentNullException(nameof(columnName));
            if (columnName.StartsWith("[") && columnName.EndsWith("]"))
            {
                columnName = columnName.Substring(1, columnName.Length - 2);
            }

            Name = columnName;
            Delimited = delimited;
            Id = -1;
            Sign = 0;
        }

        public ColumnExpression(int id)
        {
            Id = id;
            Name = $"{{{Id}}}";
            Delimited = false;
            Sign = 0;
        }

        public T Accept<T>(IExpressionVisitor<T> visitor) => visitor.Visit(this);

        public bool Equals(ColumnExpression other)
        {
            return string.Equals(Name, other.Name);
        }

        /// <inheritdoc />
        public override bool Equals(object obj)
        {
            if (obj is null) return false;
            return obj is ColumnExpression expression && Equals(expression);
        }

        /// <inheritdoc />
        public override int GetHashCode() => Name != null ? Name.GetHashCode() : 0;

        public override string ToString() => SqlGenerator.Instance.Generate(this);
        public T ToString<T>(IExpressionProcessor<T> processor) => processor.Process(this);

        public static implicit operator ColumnExpression(string columnName) => new ColumnExpression(columnName);

        public static implicit operator ColumnExpression(int id) => new ColumnExpression(id);


        public static ILogicalExpression operator ==(ColumnExpression left, IConstantExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static ILogicalExpression operator !=(ColumnExpression left, IConstantExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);

        public static ILogicalExpression operator ==(IConstantExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static ILogicalExpression operator !=(IConstantExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);


        public static ILogicalExpression operator ==(ColumnExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static ILogicalExpression operator !=(ColumnExpression left, ColumnExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);

        public static ILogicalExpression operator ==(ColumnExpression left, IValueExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.Equal);

        public static ILogicalExpression operator !=(ColumnExpression left, IValueExpression right) =>
            new ComparisonExpression(left, right, ComparisonOperator.NotEqual);


        public static ILogicalExpression operator ==(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.Equal);

        public static ILogicalExpression operator !=(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.NotEqual);


        public static ILogicalExpression operator >(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.Greater);

        public static ILogicalExpression operator <(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.Less);


        public static ILogicalExpression operator >=(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.GreaterOrEqual);

        public static ILogicalExpression operator <=(ColumnExpression left, int right) =>
            new ComparisonExpression(left, right.AsExpression(), ComparisonOperator.LessOrEqual);

        public object Tag { get; set; }
    }
}